Class 2 – 10/29/2002
Perl Variables (review and examples)
Scalars
A scalar is the simplest type of variable. It holds a single value, which can be a string or a number. Internally, Perl stores scalars as strings, which means that it is not terribly well-suited for number-crunching, since it has to keep converting strings to numbers and back all the time.

To assign a value to a scalar:
my $animal = "camel";
my $answer = 42;

Scalar values can be strings, integers or floating point numbers, and Perl will automatically convert between them as required. There is no need to pre-declare your variable types.

You can also assign several scalars at once:
($a, $b, $c) = (1, 2, 3);
($a, $b, $c) = ($c, $b, $a + ($b * $a));
The second line illustrates that values on the right are determined before the assignments happen on the left, so you can use this to swap two variables without a temporary.

Scalar values can be used in various ways:

print $animal;
print "The animal is $animal\n";
print "The square of $answer is ", $answer * $answer, "\n";

There are a number of "magic" scalars with names that look like punctuation or line noise. These special variables are used for all kinds of purposes, and a handout with these will be passed around. The only one you need to know about for now is $_ which is the "default variable". It's used as the default argument to a number of functions in Perl, and it's set implicitly by certain looping constructs.

Arrays
Arrays are ordered lists of values. The name ``array'' is traditional, although they're more akin to linked lists or deques. Use an array any time you need a list of things

To assign values to an array:
my @animals = ("camel", "llama", "owl");
my @numbers = (23, 42, 69);
my @mixed = ("camel", 42, 1.23);
@array = @otherarray;
@empty = ();

Arrays are zero-indexed. Here's how you get at elements in an array:
print $animals[0]; # prints "camel"
print $animals[1]; # prints "llama"

Some more advancedexamples:
$foo = $array[9];
$array[3] = $bar;
@other = @array[2,0,1];
@baz = @array[4..8];
($a, $b, @rest) = @array;

You can subscript anything that has an array value, e.g., literal arrays:
$foo = ("a", "b", "c")[1];

Using @array where Perl expects to find a scalar value ("in scalar context") will give you the number of elements in the array:
if (@animals < 5) { ... }

You can do various useful things to lists:
my @sorted = sort @animals;
my @backwards = reverse @numbers;

Here are some useful functions for using on arrays:
## Appends value to the end of array.
push(@array, value, ... );

## Pops the last value off of the end of array
## (shortening it by one), and returns it.
$valus = pop(@array);

## Removes the first element from the beginning
## of array (shortening it by one) and returns it.
$value = shift(@array);

## Prepends value to the beginning of array.
$value = unshift(@array, value, ...);

There are a couple of special arrays too, such as @ARGV (the command line arguments to your script) and @_ (the arguments passed to a subroutine).


Hashes
The third basic type in Perl is the hash table, also known as an associative array or hash. Like arrays, a hash is a collection of values. However, whereas array indices are integers, hash indices can be any string. You can think of arrays as being lists, and hashes as being look-up tables. Hashes have no particular internal order.

To assign values to a hash:
my %fruit_color = ("apple", "red", "banana", "yellow");

## Or the more normal way:
my %fruit_color = (
    apple => "red",
    banana => "yellow",
);

## The “=>” operator is much like a comma, but more visually appealing.

## To empty a hash:
%hash = ();

To get at hash elements:
$fruit_color{"apple"}; # gives "red"

You can get at lists of keys and values with keys() and values().
my @fruits = keys(%fruit_colors);
my @colors = values(%fruit_colors);

To remove a hash entry, use delete:
delete($fruit_color{"apple"});

Just like special scalars and arrays, there are also special hashes. The most well known of these is %ENV which contains environment variables.





Conditional and Looping Constructs

Perl has most of the usual conditional and looping constructs except for case/switch. The conditions can be any Perl expression. In the next section we will cover the list of operators commonly used for comparison.

if
if ( condition ) {
    ...
} elsif ( other condition ) {
    ...
} else {
    ...
}

There's also a negated version of it:
unless ( condition ) {
    ...
}
This is provided as a more readable version of: if (!condition).


Note that the braces are required in Perl, even if you've only got one line in the block. However, there is a clever way of making your one-line conditional blocks more English like:
## the traditional way
if ($zippy) {
    print "Yow!";
}

## the Perlish post-condition way
print "Yow!" if $zippy;
print "We have no bananas" unless $bananas;

while
while ( condition ) {
    ...
}

There's also a negated version, for the same reason we have unless:
until ( condition ) {
    ...
}

You can also use while in a post-condition:
print "LA LA LA\n" while 1; # loops forever

The do statement can also be used with while and until:
do { ... } while ( condition );
do { ... } until ( condition );

for
Exactly like C:
for (my $i=0; $i <= $max; $i++) {
    ...
}

foreach
foreach (@array) {
    print "This element is $_\n";
}

# You don't have to use the default $_ either...
foreach my $key (keys %hash) {
    print "The value of $key is $hash{$key}\n";
}




Perl's post-condition way can be used with most conditional constructs:
statement if EXPR;
statement unless EXPR;
statement while EXPR;
statement until EXPR;


Builtin Operators and Functions

Truth and other booleans
Actually, it's easier to define what is false: empty arrays and hashes, and nonexistent variables, are false. For scalars, 0 is false, as is the empty string. Actually, there are two varieties of empty string: the first is "", the second is the undefined value.

The undefined value is what you get if, say, you try to get a hash element that doesn't exist. It is similar to the NULL pointer in C. You can find out whether a variable has the undefined value by calling defined($variable) (or !defined($variable), as the case may be).

You can explicitly set a variable to the undefined value by using undef:
$var = undef;

That's it for falsehood. Anything that isn't false is true.
Arithmetic

+ addition
- subtraction
* multiplication
/ division


Numeric comparison

== equality
!= inequality
< less than
> greater than
<= less than or equal
>= greater than or equal

String comparison

eq equality
ne inequality
lt less than
gt greater than
le less than or equal
ge greater than or equal
cmp The generalized string comparison operator.
$a cmp $b returns -1 if $a is less than $b, 1 if $a is greater than $b, and 0 if they are equal.

(Why do we have separate numeric and string comparisons? Because we don't have special variable types, and Perl needs to know whether to sort numerically (where 99 is less than 100) or alphabetically (where 100 comes before 99).

Boolean logic

&& and
|| or
! not

(and, or and not aren't just in the above table as descriptions of the operators -- they're also supported as operators in their own right. They're more readable than the C-style operators, but have different precedence to && and friends.)

Miscellaneous

= assignment
. string concatenation
x string multiplication
.. range operator (creates a list of numbers)


Many operators can be combined with a = as follows:
$a += 1; # same as $a = $a + 1
$a -= 1; # same as $a = $a - 1
$a .= "\n"; # same as $a = $a . "\n";
$a <=> $b; # much like cmp above



Loop-control commands

There are times when you don't want to finish executing the body of the loop you're in. For these cases, Perl provides not one, not two, but three special commands:

Last
This is similar to C's break statement: it exits the loop immediately (without passing through the continue block, if any), causing control to continue with the next statement after the closing brace.
Next
This is similar to C's continue statement: control passes through the continue block, if any, then back up to the condition at the top of the loop.
Redo
This has no equivalent in C. It causes control to go back to the top of the while block, to the first statement after the opening brace. The continue block is not executed, and the condition is not evaluated.



Homework